declare var map: any;
declare var form: any;

/**
 * 定义GIS地图属性查询通用类
 */
export class GisAttributeSearchUtils {
    // 查询服务
    ss: any;
    // 翻译服务
    fs: any;
    // 查询参数
    paras: {
        type: string, baseUrl: string, layerName: string, inExtent?: boolean,
        extent?: any, geometryField?: string
    };
    // 元数据
    medname: string;
    // 消息服务
    msg: any;
    // 查询条件属性
    attribute: any = {};
    // 查询条件语句
    where = '';
    // 是否查询中
    searchIsLoading = false;
    // 是否重置中
    resetIsLoading = false;
    // 查询结果
    pageList: any;
    // 通用对象
    option: {
        infoTemplateId?: string, // 弹窗id
        infoWindowHeight?: string, // 弹窗高度
        infoWindowWidth?: string, // 弹窗宽度
        infoWindowOverflow?: string // 弹窗滚动样式
        clickEvent?: any, // 弹窗点击事件回调
        back?: any, // 属性查询成功点击回调

    } = {};
    // 当前查询图层空间数据类型
    geometryType: string;

    // 初始化
    constructor(msg: any, option?: {
        clickEvent?: any,
        back?: any,
        infoWindowHeight?: string,
        infoWindowWidth?: string,
        infoWindowOverflow?: string
    }) {
        this.msg = msg;
        this.option = option || {};
        this.fs = form.FormDataService;
    }

    // 属性查询主函数
    attributeSearch(attribute: any, medname: any, paras: any) {

        if (this.searchIsLoading === true) {
            return;
        }
        this.searchIsLoading = true;

        // 获取属性查询需要的参数
        this.attribute = attribute;
        this.medname = medname;
        this.paras = paras;
        this.assembleAttributeCondition(this.attribute);

        this.initAttributeSearch(this.paras.type, this.paras.baseUrl, this.paras.layerName, this.where,
            this.paras.inExtent, this.paras.extent, this.paras.geometryField, this.option);
    }


    //根据查询属性组装查询语句
    private assembleAttributeCondition(attribute: any) {
        this.where = '';
        for (const key in attribute) {
            if (attribute.hasOwnProperty) {
                if (attribute[key] === null || attribute[key] === undefined || attribute[key] === 'null' || attribute[key] === '') {
                    continue;
                }
                if (key.indexOf(':=') !== -1) {
                    const newKey = key.replace(':=', '');
                    if (typeof attribute[key] === 'string') {
                        this.where += newKey + ' = \'' + attribute[key] + '\' and ';
                    }
                    if (typeof attribute[key] === 'number' || typeof attribute[key] === 'boolean') {
                        this.where += key + ' = ' + attribute[key] + ' and ';
                    }
                } else if (key.indexOf(':like') !== -1) {
                    const newKey = key.replace(':like', '');
                    this.where += newKey + ' like ' + '\'%' + attribute[key] + '%\' and ';
                } else if (key.indexOf(':dlike') !== -1) {
                    const newKey = key.replace(':dlike', '');
                    this.where += newKey + ' like ' + '\'%,' + attribute[key] + ',%\' and ';
                } else {
                    if (typeof attribute[key] === 'string') {
                        this.where += key + ' like ' + '\'%' + attribute[key] + '%\' and ';
                    }
                    if (typeof attribute[key] === 'number' || typeof attribute[key] === 'boolean') {
                        this.where += key + ' = ' + attribute[key] + ' and ';
                    }
                }
            }
        }
        this.where = this.where.substr(0, this.where.length - 4);
    }

    // 属性查询初始化
    private initAttributeSearch(type: string, baseUrl: string, layerName: string, where: string, inExtent?: boolean,
        extent?: any, geometryField?: string, option?: any) {

        const that = this;
        option.clickEvent = option && option.clickEvent ? option.clickEvent : that.clickEventBack;
        option.back = option && option.back ? option.back : that.searchSuccessBack;
        option.infoTemplateId = layerName + '-attribute-search';

        if (!this.ss) {
            this.initAttributeService(type, option, (service: any) => {
                that.ss = service;
                that.startAttributeSearch(service, baseUrl, layerName, where, inExtent, extent, geometryField,
                    option.back);
            });
        } else {
            this.ss.clear();
            this.reInitAttributeService(type, option);
            this.startAttributeSearch(that.ss, baseUrl, layerName, where, inExtent, extent, geometryField, option.back);
        }
    }


    // 属性查询服务初始化
    private initAttributeService(type: string, option?: any, initBack?: any) {
        map.Factory.SimpleSearch('AttributeSearch', (attributeSearch) => {
            attributeSearch.init(type, {
                infoTemplateId: option.infoTemplateId,
                infoWindowHeight: option.infoWindowHeight,
                infoWindowWidth: option.infoWindowWidth,
                infoWindowOverflow: option.infoWindowOverflow,
                clickEvent: option.clickEvent
            });
            if (initBack) {
                initBack(attributeSearch);
            }
        });
    }

    // 查询服务重新初始化
    reInitAttributeService(type: string, option?: any) {
        this.ss.init(type, {
            infoTemplateId: option.infoTemplateId,
            infoWindowHeight: option.infoWindowHeight,
            infoWindowWidth: option.infoWindowWidth,
            infoWindowOverflow: option.infoWindowOverflow,
            clickEvent: option.clickEvent,
        });
    }


    // 开始属性查询
    private startAttributeSearch(service: any, baseUrl: string, layerName: string, where: string,
        inExtent?: boolean, extent?: any, geometryField?: string, back?: any) {
        const ower = this;
        service.search({
            baseUrl,
            layerName,
            where,
            inExtent,
            extent,
            geometryField
        }, (e: any) => {
            if (back) {
                back(ower);
            }
        });
    }

    // 查询成功回调
    searchSuccessBack(ower: any) {

        if (ower.ss.pageList.length === 0) {
            ower.searchIsLoading = false;
            ower.msg.warning('未查询到结果');
            return;
        }

        ower.dictionaryEscape(ower, () => {
            ower.pageList = ower.ss.pageList;
            ower.ss.localByBounds();
            ower.searchHighlight();
            ower.searchIsLoading = false;
        });
    }

    // 查询高亮
    searchHighlight() {
        this.geometryType = this.ss.datas.features[0].geometry.type;
        if (this.geometryType.includes('Point')) {
            this.ss.showFeatures();
        } else {
            const coordinates = [];
            this.ss.datas.features.forEach(feature => {
                coordinates.push(feature.geometry.coordinates[0][0]);
            });
            if (this.geometryType.includes('Line')) {
                this.ss.searchLineAndFillHighlight(coordinates, 'line');
            } else if (this.geometryType.includes('Polygon')) {
                this.ss.searchLineAndFillHighlight(coordinates, 'fill');
            }
        }
    }

    // 点击Ui高亮
    clickhHighlight(feature: any) {
        if (this.geometryType.includes('Point')) {
            this.ss.highlight(feature);
        } else {
            const coordinates = [];
            coordinates.push(feature.geometry.coordinates[0][0]);
            if (this.geometryType.includes('Line')) {
                this.ss.clickLineAndFillHighlight(coordinates, 'line');
            } else if (this.geometryType.includes('Polygon')) {
                this.ss.clickLineAndFillHighlight(coordinates, 'fill');
            }
        }
    }


    // 字典翻译
    private dictionaryEscape(ower: any, callback: any) {
        let transCount = 0;
        ower.ss.pageList.forEach(list => {
            ower.fs.dictionaryEscape(ower.medname, list.properties, (data) => {
                for (const key in data) {
                    if (data.hasOwnProperty(key) === true) {
                        if (key.indexOf('_Name') !== -1) {
                            const newKey = key.replace('_Name', '');
                            data[newKey] = data[key];
                            delete data[key];
                        }
                    }
                }
                list.properties = data;
                transCount++;
                if (transCount === ower.ss.pageList.length) {
                    if (callback) {
                        callback();
                    }
                }
            });
        });
    }

    // 点击事件回调
    clickEventBack(e: any, event?: any) {
        if (event) {
            event.stopPropagation();
        }
    }

    // 加载页数
    loadPage() {
        if (this.ss) {
            this.ss.clear();
            this.ss.loadPage();
            this.pageList = this.ss.pageList;
            this.dictionaryEscape(this, () => {
                this.ss.localByBounds();
                if (this.geometryType.includes('Point')) {
                    this.ss.showFeatures();
                }
            });
        }
    }


    // 定位
    local(item: any) {
        if (this.ss) {
            if (item && item.type && item.geometry) {
                let bounds: [number, number, number, number] = [360, 180, 0, 0];
                map.Factory.Utils('GeojsonUtils', (geojsonUtils) => {
                    bounds = geojsonUtils.getGeojsonBoundingBox(item);
                    form.ConfigService.map.flyTo({ xmin: bounds[0], ymin: bounds[1], xmax: bounds[2], ymax: bounds[3] });
                });
            }
        }
    }

    // 重置
    reset() {
        if (this.resetIsLoading === true) {
            return;
        }

        this.resetIsLoading = true;

        this.attribute = {};
        this.pageList = [];
        this.searchIsLoading = false;
        if (this.ss) {
            this.ss.reset();
            this.ss.clear();
            if (!this.geometryType.includes('Point')) {
                this.ss.clearSearchHighlight();
                this.ss.clearClickHighlight();
            }
        }

        this.resetIsLoading = false;
    }

    // 配置改变
    change() {
        this.attribute = {};
        this.pageList = [];
        if (this.ss) {
            this.ss.reset();
            this.ss.clear();
        }
        this.searchIsLoading = false;
        this.resetIsLoading = false;
    }

}
